# 版本号 VERSION 0.3.5

import os, time, threading
import fitz # pip install PyMuPDF
import pandas # pip install pandas openpyxl xlrd

from sys import exit
from tkinter import filedialog, Tk

# 设置全局变量
VERSION = 'v0.3.5'
WORKPATH = os.getcwd()  # 获取软件的当前工作目录
TASKS = [] # 多线程任务
ERR_CODE = 0 # 本程序自定义错误代码
os.system('title Qovi PDF Tools 转换为图片 %s' % VERSION)
root = Tk()
root.withdraw() # 修复弹出空白窗口问题

# 多线程类 (用于转换格式)
class convertTask(threading.Thread):
    def __init__(self,threadId,name,input,output):
        threading.Thread.__init__(self)
        self.threadId = threadId
        self.name = name
        self.input = input
        self.output = output

    def run(self):
        convert_img(self.input,self.output)

# 封装: 异步模式调用ffmpeg对png图片进行转换 (目标jpg)
def convert_img(input = '', output = ''):
    # 把 png 图片 转换为 jpg 图片
    print('ffmpeg.exe -i %s -q 0 %s' %(input, output))
    os.system('"'+ WORKPATH +r'\bin\ffmpeg.exe" -i '+'%s -q 0 %s' %(input, output) +' -loglevel quiet') # -loglevel quiet: ffmpeg 以静默的模式运行
    # 删除 png 缓存
    os.system('del '+ input)

# 请求选择 PDF文件 以及 Excel表格命名模板
print('请打开 PDF 文件: (.pdf)')
inputFile = filedialog.askopenfilename(title='打开 PDF 文件', filetypes=(('可携带文件格式', '*.pdf'),))
if not inputFile:
    print('用户取消操作，按任意键退出 ...')
    os.system('pause >nul')
    exit()
print(inputFile, '\n')
print('请打开命名模板: (目前仅支持 .xls .xlsx)')
inputScript = filedialog.askopenfilename(title='打开命名模板', filetypes=(('Microsoft Excel 工作表', '*.xls *.xlsx'),))
print(inputScript, '\n')

# 请求使用哪一列进行命名
if inputScript: column = input('使用哪一列进行命名? : (默认值为\'證書編號\') ') or '證書編號'

# 读取 Excel表格命名模板 的数据
cert_num = []
try:
    content = pandas.read_excel(inputScript)
    print(content[column])
    cert_num = content[column]
except FileNotFoundError as fe:
    print(fe)
    ERR_CODE = 1
except KeyError as ke:
    print(ke)
    ERR_CODE = 2

# 如果没有传入命名模板或报错, 则检测 pdf 页数并按数字开始命名
if ERR_CODE>0:
    custom_name = input('输入自定义命名模板: 规则：字符串 + "#"表示插入数字 \n(若无规则请直接按下回车)')
    ran = eval(input('请输入数字的开始序号: ') or '1')
    num_bit = custom_name.count('#')    # 统计 custom_name 数字占位符数量
    print('数字占位符为: ',num_bit)

    startTime_pdf2img = time.time()     # 开始时间
    pdfDoc = fitz.open(inputFile)       # 操作打开 PDF

    # 根据用户规则进行生成命名
    # for i in range(ran, ran + pdfDoc.page_count):
    #     rename = custom_name.replace('#','')
    #     # 数字部分缺少位数则补 0
    #     for j in range(num_bit - len(str(i))):
    #         rename += '0'
    #     rename += str(i)
    #     print(rename)
    if not custom_name:     # 如果无输入, 则直接使用纯数字序列命名
        for i in range(1, pdfDoc.page_count + 1):
            cert_num.append(i)
    else:
        for i in range(ran, ran + pdfDoc.page_count):
            rename = custom_name.replace('#','')
            # 数字部分缺少位数则补 0
            for j in range(num_bit - len(str(i))):
                rename += '0'
            rename += str(i)
            cert_num.append(rename)
else:
    startTime_pdf2img = time.time()     # 开始时间
    pdfDoc = fitz.open(inputFile)       # 操作打开 PDF

# 遍历 PDF 文件中每一页, 开始转换操作
for pg in range(pdfDoc.page_count):
    page = pdfDoc[pg]
    rotate = int(0)
    # 设置缩放系数
    # 此处若是不做设置, 默认图片分辨率较低, dpi=96, 所以需要缩放
    zoom_x = float(3.0)
    zoom_y = float(3.0)
    mat = fitz.Matrix(zoom_x, zoom_y).prerotate(rotate)
    pix = page.get_pixmap(matrix=mat, alpha=False)

    # 将工作目录切换到选择的 PDF 文件下
    pagePath = os.path.dirname(inputFile)
    os.chdir(pagePath)

    # 判断存放图片的文件夹是否存在, 若不存在则创建
    if not os.path.exists('certificate'):
        os.makedirs('certificate')
    
    # 将图片写入指定的文件夹内
    pix._writeIMG('certificate/temp%s.png' % pg, 1)  
    # print('compelete write certificate/temp%s.png' % pg)

    # 转换 PNG 图片 为 JPEG 图片
    # convert_img('.\certificate\\temp%s.png' % pg, '.\certificate\\%s.jpg' % cert_num[pg])
    TASKS.append(convertTask(1,"FFmpeg-seq%s" % pg, '.\certificate\\temp%s.png' % pg, '.\certificate\\%s.jpg' % cert_num[pg]).start())

# 等待所有子线程结束, 并释放任务池
for t in TASKS: 
    try: t.join()
    except Exception as e: pass
endTime_pdf2img = time.time()   # 结束时间
print('\nPDF To Image 本过程耗时', int(endTime_pdf2img - startTime_pdf2img), '秒')  # 计算总过程时间
print('按任意键退出程序 ...')
os.system('pause >nul')